package com.yunhe.abnormal.repository.DAO;

import com.yunhe.abnormal.domain.base.AbnormalRule;
import com.yunhe.common.model.data.AbnormalRuleFormulaObject;
import com.yunhe.abnormal.repository.base.AbnormalRuleFormulaObjectRepository;
import org.neo4j.ogm.model.Result;
import org.neo4j.ogm.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.*;

@Repository
public class AbnormalRuleRepositoryDao {

    @Autowired
    private Session session;
    @Autowired
    private AbnormalRuleFormulaObjectRepository abnormalRuleFormulaObjectRepository;

    private List<AbnormalRule> getAbnormalRules(Result results) {
        List<AbnormalRule> abnormalRuleList = new ArrayList<>();
        for (Map<String, Object> result : results) {
            AbnormalRule abnormalRule = new AbnormalRule();
            abnormalRule.setId((Long) result.get("id"));
            abnormalRule.setTitle(String.valueOf(result.get("title")));
            abnormalRule.setName(String.valueOf(result.get("name")));
            abnormalRule.setObjectId((Long) result.get("objectId"));
            abnormalRule.setObjectTitle(String.valueOf(result.get("objectTitle")));
            abnormalRule.setSn((Long) result.get("sn"));
            abnormalRuleList.add(abnormalRule);
        }
        return abnormalRuleList;
    }

    private AbnormalRule getAbnormalRule(Result result) {
        List<AbnormalRule> abnormalRules = getAbnormalRules(result);
        if (abnormalRules !=null && !abnormalRules.isEmpty()) {
            return abnormalRules.get(0);
        }
        return null;
    }

    /**
     * 执行语句搜索设备告警条件
     *
     * @param cypher
     * @return
     */
    public List<Map<String, Object>> search(String cypher) {
        Result result = session.query(cypher, new HashMap<>());
        Iterator<Map<String, Object>> iterator = result.iterator();
        List<Map<String, Object>> list = new ArrayList<>();
        while (iterator.hasNext()) {
            list.add(iterator.next());
        }
        return list;
    }

    /**
     * 得到排序规则
     *
     * @param sortList 排序字段列表
     * @return
     */
    private String getSort(List<String> sortList) {
        String sort = " order by ";
        for (String s : sortList) {
            if (s.startsWith("-")) {
                s = s.replace("-", "");
                sort += "ar." + s + " DESC,";
            } else {
                sort += "ar." + s + ",";
            }
        }
        sort = sort.substring(0, sort.length() - 1);
        return sort;
    }

    /**
     * 得到分页条件
     *
     * @param page 页数
     * @param size 每页条数
     * @return
     */
    private String getPage(int page, int size) {
        return " skip " + page * size + " limit " + size;
    }

    public Map<String, Object> getAbnormalRules(Optional<List<Long>> stationIds,
                                                Optional<Long> objectId,
                                                Optional<String> queryStr,
                                                int page,
                                                int size,
                                                List<String> sortList) {
        Map<String, Object> map = new HashMap<>();
        String cql = "match (obj)-[:HAS_ABNORMAL_RULE]->(ar:AbnormalRule)-[:ALARM_LEVEL_OF]->(al:AlarmLevel) with ar ";
        if (stationIds.isPresent()) {
            map.put("stationIds", stationIds.get());
            //电站到设备最长路径为Station->EnergyUnit->Device
            cql += " match (s:Station)-[*0..4]->(ar) where ID(s) in {stationIds} with ar";
        }
        if (objectId.isPresent()) {
            map.put("objectId", objectId.get());
            cql += " match (object)-[:HAS_ABNORMAL_RULE]->(ar) where ID(object)={objectId} with ar";
        }
        if (queryStr.isPresent()) {
            map.put("queryStr", queryStr.get());
            cql += " match (ar)-[:ALARM_LEVEL_OF]->(b:AlarmLevel) where ar.title contains {queryStr} or ar.description contains {queryStr} or b.title " +
                    "contains {queryStr} with ar ";
        }
        if (sortList != null) {
            String sort = getSort(sortList);
            cql += sort;
        }
        String countCql = cql + " with distinct ar return count (ar) ";
        Iterable<Long> counts = session.query(Long.class, countCql, map);
        Long count = 0L;
        if (counts.iterator().hasNext()) {
            count = counts.iterator().next();
        }
        if (page >= 0 && size > 0) {
            String pageStr = getPage(page, size);
            cql += pageStr;
        }
        cql += " with distinct ar " +
                "match (object)-[:HAS_ABNORMAL_RULE]->(ar) " +
                "return ID(ar) as id, ar.title as title, ar.name as name, ar.sn as sn, ID(object) as objectId, object.title as objectTitle";
        Result result = session.query(cql, map);
        List<AbnormalRule> resultRule = getAbnormalRules(result);
        Map<String, Object> results = new HashMap<>();
        results.put("result", resultRule);
        results.put("count", count);
        return results;
    }

    public AbnormalRule findById(Long id) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("id", id);
        String cql = "match (object)-[:HAS_ABNORMAL_RULE]->(ar) where ID(ar) = {id}" +
                "return ID(ar) as id, ar.title as title, ar.name as name, ar.sn as sn, ID(object) as objectId, object.title as objectTitle";
        Result result = session.query(cql, paramMap);
        AbnormalRule abnormalRule = getAbnormalRule(result);
        List<AbnormalRuleFormulaObject> formulaObjects = abnormalRuleFormulaObjectRepository.findByRuleId(id);
        abnormalRule.setAbnormalRuleFormulaObjects(formulaObjects);
        return abnormalRule;
    }

    public AbnormalRule findByTitleAndObject(String title, Long objectId) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("title", title);
        paramMap.put("objectId", objectId);
        String cql = "match (object)-[:HAS_ABNORMAL_RULE]->(ar:AbnormalTitle) where ID(object) = {objectId} and ar.title = {title} " +
                "return ID(ar) as id, ar.title as title, ar.name as name, ar.sn as sn, ID(object) as objectId, object.title as objectTitle";
        Result result = session.query(cql, paramMap);
        AbnormalRule abnormalRule = getAbnormalRule(result);
        return abnormalRule;
    }
}
